package com.example.quartz.core;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.example.quartz.dao.QrtzJobLogMapper;
import com.example.quartz.model.QrtzJobLog;
import com.example.quartz.utils.IdGen;
import com.example.quartz.utils.enums.ExecStatus;

/**
 * @Class TransactionJob
 * @Description 事务型任务
 * @Author xw
 * @Date 2017年3月31日17:24:07
 */
public abstract class UtilTransactionJob implements Job {

	protected Logger _log = LoggerFactory.getLogger(this.getClass());

	public static final String TRANSACTION_TEMPLATE = "transactionTemplate";
	public static final String JOB_LOG_DAO = "jobLogDao";

	private TransactionTemplate transactionTemplate;
	private QrtzJobLogMapper qrtzJobLogDao;

	@Override
	public final void execute(JobExecutionContext context) throws JobExecutionException {
		// TODO 分布式事务
		JobDataMap data = context.getJobDetail().getJobDataMap();
		this.transactionTemplate = (TransactionTemplate) data.get(TRANSACTION_TEMPLATE);
		this.qrtzJobLogDao = (QrtzJobLogMapper) data.get(JOB_LOG_DAO);

		_log.info("事务型任务开始执行");
		JobKey jobKey = context.getJobDetail().getKey();
		TriggerKey triggerKey = context.getTrigger().getKey();
		QrtzJobLog jobLog = new QrtzJobLog();
		jobLog.setId(IdGen.uuid());
		jobLog.setJobName(jobKey.getName());
		jobLog.setJobGroup(jobKey.getGroup());
		jobLog.setTriggerName(triggerKey.getName());
		jobLog.setTriggerGroup(triggerKey.getGroup());
		jobLog.setExecFireTime(context.getScheduledFireTime());
		Date now = new Date();
		jobLog.setExecStartTime(now);
		jobLog.setCreateDate(now);

		try {
			run(context);
			jobLog.setExecStatus(ExecStatus.OK.name());
			_log.info("事务型任务执行正常结束");
		} catch (Throwable e) {
			jobLog.setExecStatus(ExecStatus.ERROR.name());
			_log.error("事务型任务执行出现异常被中断", e);
		} finally {
			now = new Date();
			jobLog.setExecEndTime(now);
			jobLog.setUpdateDate(now);
			transactionTemplate.execute(new TransactionCallbackWithoutResult() {
				protected void doInTransactionWithoutResult(TransactionStatus status) {
					try {
						qrtzJobLogDao.insertSelective(jobLog);
					} catch (Exception e) {
						_log.error("保存定时任务执行日志异常");
					}
				}
			});
		}

	}

	/**
	 * @Title run
	 * @Description 任务运行
	 * @Author xw
	 * @Date 2017年3月31日17:24:07
	 * @param context
	 * @throws JobExecutionException
	 */
	protected abstract void run(JobExecutionContext context) throws JobExecutionException;

}
